package edu.ptu.acl.filter;

import edu.ptu.acl.common.MyConstants;
import edu.ptu.acl.common.RequestHolder;
import edu.ptu.acl.dto.TokenPayload;
import edu.ptu.acl.entity.User;
import edu.ptu.acl.utils.JWTUtil;
import edu.ptu.acl.utils.RedisUtil;
import edu.ptu.acl.utils.ResponseUtils;
import org.apache.commons.lang3.StringUtils;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
import java.util.regex.Pattern;

public class LoginFilter implements Filter {

    protected static Set<String> blankUrlRegexSet = new HashSet<>();

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        blankUrlRegexSet.add("/login/.*/.*");
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) servletRequest;
        HttpServletResponse resp = (HttpServletResponse) servletResponse;

        String currentUrl = req.getServletPath();

        // 白名单，直接放行
        for (String blankUrl : blankUrlRegexSet) {
            if (Pattern.matches(blankUrl,currentUrl)) {
                filterChain.doFilter(servletRequest,servletResponse);
                return;
            }
        }

        String token = req.getHeader("Authorization");
        if (StringUtils.isEmpty(token)){
            // 没带来token，等于没登陆
            ResponseUtils.flushFaild(resp,MyConstants.ResultCode.USER_NOT_LOGIN);
            return;
        }
        TokenPayload tokenPayload = null;
        try{
            tokenPayload = JWTUtil.parseToken(token);
        }catch (Exception ex){
            // 解析token出错，要吗过期，要吗被改
            ResponseUtils.flushFaild(resp,MyConstants.ResultCode.TOKEN_PARSE_ERROR);
            return;
        }

        String snowId = (String) RedisUtil.getValue(tokenPayload.getUserId().toString());
        // 没有sonwID，登陆超时了
        if (StringUtils.isEmpty(snowId)){
            ResponseUtils.flushFaild(resp,MyConstants.ResultCode.USER_LOGIN_EXP_TIME);
            return;
        }
        // sonwID不一致，代表用户在其他地方登陆了
        if(!StringUtils.equals(tokenPayload.getSnowId().toString(),snowId)){
            ResponseUtils.flushFaild(resp,MyConstants.ResultCode.USER_LOGIN_OTHER_CLIENT);
            return;
        }

        User user = (User) RedisUtil.getValue(snowId);

        // 将当前用户绑定在线程上
        RequestHolder.add(user);

        // 刷新redis中的key的过期时间
        // redis插入值，设置过期时间30分钟
        RedisUtil.setValue(user.getId().toString(), snowId
                , MyConstants.RedisExTime.USER_LOGIN_EX_TIME.getExTime(), MyConstants.RedisExTime.USER_LOGIN_EX_TIME.getTimeUnit());
        RedisUtil.setValue(snowId,user
                , MyConstants.RedisExTime.USER_LOGIN_EX_TIME.getExTime(), MyConstants.RedisExTime.USER_LOGIN_EX_TIME.getTimeUnit());

        filterChain.doFilter(servletRequest,servletResponse);
    }

    @Override
    public void destroy() {

    }
}
